package com.zhz.system.config.shiro;

import com.zhz.common.shiro.entity.UserProfileResponse;
import com.zhz.common.shiro.realm.IhrmRealm;
import com.zhz.model.system.contract.dto.PermissionDTO;
import com.zhz.model.system.contract.dto.UserDTO;
import com.zhz.model.system.contract.param.PermissionQueryParam;
import com.zhz.model.system.contract.param.UserQueryParam;
import com.zhz.system.contract.enums.PermissionEnVisibleEnum;
import com.zhz.system.contract.enums.UserLevelEnum;
import com.zhz.system.repository.service.*;
import com.zhz.system.utils.UserProfileResponseUtil;
import org.apache.shiro.authc.*;

import java.util.List;
import java.util.Objects;

/**
 * @author zhouhengzhe
 * @date 2023/5/28
 */
public class UserRealm extends IhrmRealm {

    private final UserService userService;

    private final PermissionService permissionService;

    private final UserRoleService userRoleService;

    private final RoleService roleService;

    private final RolePermissionService rolePermissionService;

    public UserRealm(UserService userService,
                     PermissionService permissionService,
                     UserRoleService userRoleService,
                     RoleService roleService,
                     RolePermissionService rolePermissionService) {
        this.userService = userService;
        this.permissionService = permissionService;
        this.userRoleService = userRoleService;
        this.roleService = roleService;
        this.rolePermissionService = rolePermissionService;
    }

    /**
     * 认证方法
     *
     * @param authenticationToken token
     * @return 返回认证信息
     * @throws AuthenticationException 认证错误
     */
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
        // 1.获取用户的手机号和密码
        UsernamePasswordToken usernamePasswordToken = (UsernamePasswordToken) authenticationToken;
        String mobile = usernamePasswordToken.getUsername();
        String password = new String(usernamePasswordToken.getPassword());
        // 2.根据手机号查询用户
        UserDTO userDTO = userService.getOne(UserQueryParam.builder().mobile(mobile).build());
        // 3.判断用户是否存在，用户密码是否和输入密码一致
        if (Objects.nonNull(userDTO) && userDTO.getPassword().equals(password)) {
            //4、构造安全数据并返回（安全数据：用户基本数据，权限信息 UserProfileResponse）
            //根据不同的用户级别获取用户权限
            UserProfileResponse userProfileResponse = UserProfileResponse
                    .builder()
                    .userId(userDTO.getId())
                    .mobile(userDTO.getMobile())
                    .username(userDTO.getUsername())
                    .company(userDTO.getCompanyName())
                    .companyId(userDTO.getCompanyId())
                    .build();
            if (UserLevelEnum.USER.getMessage().equals(userDTO.getLevel())) {
                UserProfileResponseUtil.build(userProfileResponse,
                        userRoleService,
                        userDTO,
                        roleService,
                        rolePermissionService,
                        permissionService);
            } else {
                PermissionQueryParam permissionQueryParam = new PermissionQueryParam();
                if (UserLevelEnum.CO_ADMIN.getMessage().equals(userDTO.getLevel())) {
                    permissionQueryParam.setEnVisible(PermissionEnVisibleEnum.VISIBLE.getCode());
                }
                List<PermissionDTO> permissionDTOS = permissionService.list(permissionQueryParam);
                UserProfileResponseUtil.build(userProfileResponse, permissionDTOS);
            }
            //构造方法：安全数据，密码，realm域名
            return new SimpleAuthenticationInfo(userProfileResponse, userDTO.getPassword(), this.getName());
        }
        //返回null，会抛出异常，标识用户名和密码不匹配
        return null;
    }
}
